feat(spanner): add Client Context support to options#1499
feat(spanner): add Client Context support to options#1499olavloite merged 12 commits intogoogleapis:mainfrom
Conversation
This change adds support for ClientContext in Options and ensures it is propagated to ExecuteSql, Read, Commit, and BeginTransaction requests. It aligns with go/spanner-client-scoped-session-state design. ClientContext allows passing opaque, RPC-scoped side-channel information (like application-level user context) to Spanner. This implementation supports setting ClientContext at the Client, Database, and Request levels, with request-level options taking precedence. Key changes: - Added ClientContext to types/spanner.py and exposed it. - Updated Client.__init__ to accept a default client_context. - Added helpers for merging ClientContext with correct precedence. - Updated Snapshot, Transaction, Batch, and Database wrappers to propagate the context. - Added comprehensive unit tests in tests/unit/test_client_context.py.
- Update Session.transaction to accept client_context. - Update unit tests to support client_context propagation. - Update mock objects in tests to match the expected attribute hierarchy. - Clean up nested imports in test files.
Implement a double-checked locking pattern in Transaction and _SnapshotBase methods. When multiple threads attempt to use a lazy transaction simultaneously, they race to acquire the lock. Previously, losing threads would acquire the lock and blindly send another 'begin transaction' request, ignoring that the winner had already initialized the transaction ID. This change ensures that threads re-check self._transaction_id after acquiring the lock. If the ID is present, they skip the initialization request and use the established ID.
- Fix critical security vulnerability in where in-place modification of the base object could lead to context leakage across requests. - Replace with throughout , , , and for better robustness and subclass support. - Simplify construction logic in for better readability. Based on suggestions from Gemini Code Assist.
Summary of ChangesHello @aseering, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces comprehensive support for Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request effectively adds support for ClientContext across the Spanner client library, allowing for more granular control over request options. The changes are consistently applied through various layers of the API, from the client down to individual transactions and snapshots. The addition of a comprehensive test suite for the new functionality is also a great inclusion. I have one suggestion to improve maintainability by refactoring a duplicated block of code into a shared helper function.
google/cloud/spanner_v1/batch.py
Outdated
| if client_context is not None: | ||
| if isinstance(client_context, dict): | ||
| client_context = ClientContext(client_context) | ||
| elif not isinstance(client_context, ClientContext): | ||
| raise TypeError("client_context must be a ClientContext or a dict") | ||
| self._client_context = client_context |
There was a problem hiding this comment.
This block of code for validating and converting client_context is duplicated in several places (e.g., _BatchBase, MutationGroups, Client, _SnapshotBase). To improve maintainability and reduce code duplication, consider extracting this logic into a helper function in google/cloud/spanner_v1/_helpers.py.
|
📢 Migration Notice: 📢 This library is moving to the google-cloud-python monorepo soon. We kept this PR open due to recent activity. We would like to finalize this PR so it can be merged if it is critical. If we don't hear from the PR author, we will close this PR in the next few days. The PR can then be re-opened in the monorepo once the migration is complete and work can continue there. |
|
The test failures in this PR are not different from the failures in #1510, indicating that this PR is not introducing any new problems. |
PR created by the Librarian CLI to generate Cloud Client Libraries code from protos. BEGIN_COMMIT BEGIN_NESTED_COMMIT docs: A comment for field `routing_hint` in messages `.google.spanner.v1.ResultSet` and `.google.spanner.v1.PartialResultSet` are changed PiperOrigin-RevId: 878019893 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@5c9602db](googleapis/googleapis@5c9602db) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: A comment in message `.google.spanner.v1.TransactionOptions.ReadWrite.ReadLockMode` is changed PiperOrigin-RevId: 878019893 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@5c9602db](googleapis/googleapis@5c9602db) END_NESTED_COMMIT BEGIN_NESTED_COMMIT feat: include cache updates and routing hint into BeginTransaction and Commit request/response respectively PiperOrigin-RevId: 878019893 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@5c9602db](googleapis/googleapis@5c9602db) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: A comment for field `params` in message `.google.spanner.v1.PartitionQueryRequest` is changed PiperOrigin-RevId: 865546011 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@8d30990f](googleapis/googleapis@8d30990f) END_NESTED_COMMIT BEGIN_NESTED_COMMIT feat: include cache updates into the ResultSet response PiperOrigin-RevId: 865546011 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@8d30990f](googleapis/googleapis@8d30990f) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: A comment for field `transaction_tag` in message `.google.spanner.v1.RequestOptions` is changed PiperOrigin-RevId: 865546011 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@8d30990f](googleapis/googleapis@8d30990f) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: A comment for field `param_types` in message `.google.spanner.v1.PartitionQueryRequest` is changed PiperOrigin-RevId: 865546011 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@8d30990f](googleapis/googleapis@8d30990f) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: A comment for field `commit_timestamp` in message `.google.spanner.v1.BatchWriteResponse` is changed PiperOrigin-RevId: 865546011 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@8d30990f](googleapis/googleapis@8d30990f) END_NESTED_COMMIT BEGIN_NESTED_COMMIT chore: adjust initial_poll_delay for CreateDatabase and UpdateDatabaseDdl LRO operations PiperOrigin-RevId: 853884590 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@136a2c43](googleapis/googleapis@136a2c43) END_NESTED_COMMIT BEGIN_NESTED_COMMIT feat: add a ClientContext field to Spanner requests PiperOrigin-RevId: 853323071 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@211d22fa](googleapis/googleapis@211d22fa) END_NESTED_COMMIT BEGIN_NESTED_COMMIT feat: add Secure Parameters to the ClientContext PiperOrigin-RevId: 853323071 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@211d22fa](googleapis/googleapis@211d22fa) END_NESTED_COMMIT BEGIN_NESTED_COMMIT feat: Exposing total CPU related fields in AutoscalingConfig PiperOrigin-RevId: 845819318 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@6e20492a](googleapis/googleapis@6e20492a) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: Update high_priority_cpu_utilization_percent in AutoscalingConfig to be Optional and clarify its behavior when not specified PiperOrigin-RevId: 845819318 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@6e20492a](googleapis/googleapis@6e20492a) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: minor update for Spanner Location API PiperOrigin-RevId: 834841888 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@ded7ed1e](googleapis/googleapis@ded7ed1e) END_NESTED_COMMIT END_COMMIT This pull request is generated with proto changes between [googleapis/googleapis@a17b84ad](googleapis/googleapis@a17b84a) (exclusive) and [googleapis/googleapis@5c9602db](googleapis/googleapis@5c9602d) (inclusive). Librarian Version: v1.0.2-0.20260309131826-42ac5c451239 Language Image: us-central1-docker.pkg.dev/cloud-sdk-librarian-prod/images-prod/python-librarian-generator@sha256:b8058df4c45e9a6e07f6b4d65b458d0d059241dd34c814f151c8bf6b89211209 Fixes #1527 This PR also moves `ClientContext` under `RequestOptions` as per #1527 (comment). `ClientContext` was added in #1499 but the feature has not been released yet so it is safe to move.
PR created by the Librarian CLI to generate Cloud Client Libraries code from protos. BEGIN_COMMIT BEGIN_NESTED_COMMIT docs: A comment for field `routing_hint` in messages `.google.spanner.v1.ResultSet` and `.google.spanner.v1.PartialResultSet` are changed PiperOrigin-RevId: 878019893 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@5c9602db](googleapis/googleapis@5c9602db) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: A comment in message `.google.spanner.v1.TransactionOptions.ReadWrite.ReadLockMode` is changed PiperOrigin-RevId: 878019893 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@5c9602db](googleapis/googleapis@5c9602db) END_NESTED_COMMIT BEGIN_NESTED_COMMIT feat: include cache updates and routing hint into BeginTransaction and Commit request/response respectively PiperOrigin-RevId: 878019893 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@5c9602db](googleapis/googleapis@5c9602db) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: A comment for field `params` in message `.google.spanner.v1.PartitionQueryRequest` is changed PiperOrigin-RevId: 865546011 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@8d30990f](googleapis/googleapis@8d30990f) END_NESTED_COMMIT BEGIN_NESTED_COMMIT feat: include cache updates into the ResultSet response PiperOrigin-RevId: 865546011 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@8d30990f](googleapis/googleapis@8d30990f) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: A comment for field `transaction_tag` in message `.google.spanner.v1.RequestOptions` is changed PiperOrigin-RevId: 865546011 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@8d30990f](googleapis/googleapis@8d30990f) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: A comment for field `param_types` in message `.google.spanner.v1.PartitionQueryRequest` is changed PiperOrigin-RevId: 865546011 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@8d30990f](googleapis/googleapis@8d30990f) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: A comment for field `commit_timestamp` in message `.google.spanner.v1.BatchWriteResponse` is changed PiperOrigin-RevId: 865546011 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@8d30990f](googleapis/googleapis@8d30990f) END_NESTED_COMMIT BEGIN_NESTED_COMMIT chore: adjust initial_poll_delay for CreateDatabase and UpdateDatabaseDdl LRO operations PiperOrigin-RevId: 853884590 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@136a2c43](googleapis/googleapis@136a2c43) END_NESTED_COMMIT BEGIN_NESTED_COMMIT feat: add a ClientContext field to Spanner requests PiperOrigin-RevId: 853323071 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@211d22fa](googleapis/googleapis@211d22fa) END_NESTED_COMMIT BEGIN_NESTED_COMMIT feat: add Secure Parameters to the ClientContext PiperOrigin-RevId: 853323071 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@211d22fa](googleapis/googleapis@211d22fa) END_NESTED_COMMIT BEGIN_NESTED_COMMIT feat: Exposing total CPU related fields in AutoscalingConfig PiperOrigin-RevId: 845819318 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@6e20492a](googleapis/googleapis@6e20492a) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: Update high_priority_cpu_utilization_percent in AutoscalingConfig to be Optional and clarify its behavior when not specified PiperOrigin-RevId: 845819318 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@6e20492a](googleapis/googleapis@6e20492a) END_NESTED_COMMIT BEGIN_NESTED_COMMIT docs: minor update for Spanner Location API PiperOrigin-RevId: 834841888 Library-IDs: google-cloud-spanner Source-link: [googleapis/googleapis@ded7ed1e](googleapis/googleapis@ded7ed1e) END_NESTED_COMMIT END_COMMIT This pull request is generated with proto changes between [googleapis/googleapis@a17b84ad](googleapis/googleapis@a17b84a) (exclusive) and [googleapis/googleapis@5c9602db](googleapis/googleapis@5c9602d) (inclusive). Librarian Version: v1.0.2-0.20260309131826-42ac5c451239 Language Image: us-central1-docker.pkg.dev/cloud-sdk-librarian-prod/images-prod/python-librarian-generator@sha256:b8058df4c45e9a6e07f6b4d65b458d0d059241dd34c814f151c8bf6b89211209 Fixes googleapis/python-spanner#1527 This PR also moves `ClientContext` under `RequestOptions` as per googleapis/python-spanner#1527 (comment). `ClientContext` was added in googleapis/python-spanner#1499 but the feature has not been released yet so it is safe to move.
Re-opening #1495 due to permissions issues.
Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
Fixes #<issue_number_goes_here> 🦕